package edu.gmu.dglidde2.ece612.scheduler;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.HashSet;

import org.junit.Before;
import org.junit.Test;

/**
 * Unit test suite for validation of {@link Task} objects using the
 * {@link Task#isValid()} method.
 * 
 * @author Doug Glidden
 */
public class ValidateTask {
	private Task task;

	/**
	 * Creates a {@link Task} to be used in the test.
	 * 
	 * @see Before
	 */
	@Before
	public void createTask() {
		task = new Task();
	}

	/**
	 * Tests setting all properties to valid values.
	 */
	@Test
	public void testAllPropertiesValid() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);
		task.setProcessorNames(new HashSet<>(Arrays.asList("N0")));

		assertTrue(task.isValid());
	}

	/**
	 * Tests the use of default values for optional properties (processor
	 * names).
	 */
	@Test
	public void testDefaultOptionalPropertiesValues() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertTrue(task.isValid());
	}

	/**
	 * Tests the use of the default value for the name.
	 */
	@Test
	public void testDefaultNameValue() {
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of the default value for the phase.
	 */
	@Test
	public void testDefaultPhaseValue() {
		task.setName("P1");
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertTrue(task.isValid());
	}

	/**
	 * Tests the use of the default value for the period.
	 */
	@Test
	public void testDefaultPeriodValue() {
		task.setName("P1");
		task.setPhase(0);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of the default value for the maximum execution time.
	 */
	@Test
	public void testDefaultExecutionTimeValue() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of the default value for the relative deadline.
	 */
	@Test
	public void testDefaultRelativeDeadlineValue() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(2);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of equal values for the phase and period.
	 */
	@Test
	public void testPhaseEqualsPeriod() {
		task.setName("P1");
		task.setPhase(1);
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of a phase value greater than the period value.
	 */
	@Test
	public void testPhaseGreaterThanPeriod() {
		task.setName("P1");
		task.setPhase(2);
		task.setPeriod(1);
		task.setExecutionTime(2);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

	/**
	 * Tests the use of equal values for the maximum execution time and relative
	 * deadline.
	 */
	@Test
	public void testExecutionTimeEqualsRelativeDeadline() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(3);
		task.setRelativeDeadline(3);

		assertTrue(task.isValid());
	}

	/**
	 * Tests the use of a maximum execution time value greater than the relative
	 * deadline value.
	 */
	@Test
	public void testExecutionTimeGreaterThanRelativeDeadline() {
		task.setName("P1");
		task.setPhase(0);
		task.setPeriod(1);
		task.setExecutionTime(4);
		task.setRelativeDeadline(3);

		assertFalse(task.isValid());
	}

}
